package com.atguigu.yygh.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.yygh.enums.AuthStatusEnum;
import com.atguigu.yygh.hosp.globalexp.YyghException;
import com.atguigu.yygh.hosp.util.HttpUtils;
import com.atguigu.yygh.hosp.util.JwtHelper;
import com.atguigu.yygh.model.hosp.Hospital;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.user.mapper.UserInfoMapper;
import com.atguigu.yygh.user.service.PatientService;
import com.atguigu.yygh.user.service.UserInfoService;
import com.atguigu.yygh.vo.user.LoginVo;
import com.atguigu.yygh.vo.user.UserAuthVo;
import com.atguigu.yygh.vo.user.UserInfoQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    UserInfoMapper userInfoMapper;
    @Autowired
    PatientService patientService;

    @Override
    public Map login(LoginVo loginVo) {
        //1.参数非空校验
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();

        if(StringUtils.isEmpty(phone)){
            throw new YyghException(20001,"手机号为空");
        }

        if(StringUtils.isEmpty(code)){
            throw new YyghException(20001,"验证码为空");
        }

        //2.获取该手机号正确的验证码
        String codeFromRedis = stringRedisTemplate.boundValueOps(phone).get();
        if(!code.equals(codeFromRedis)){
            throw new YyghException(20001,"验证码校验失败");
        }

        //3.判断该手机号用户是否存在
        UserInfo userInfo = this.getUserInfoByPhone(phone);
        if(userInfo==null){
        //4.如果手机号不存在,就自动进行注册
            userInfo=new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setAuthStatus(AuthStatusEnum.NO_AUTH.getStatus());  //0代表的是未认证
            userInfo.setStatus(1);  //0-锁定 1-正常
            int insert = baseMapper.insert(userInfo);
            if(insert<=0){
                throw new YyghException(20001,"自动注册失败");
            }
        }
        //5.判断用户的状态(0-锁定 1-正常)
        if(userInfo.getStatus()==0){
            throw new YyghException(20001,"用户被锁定,不允许登录");
        }

        //6.返回值格式有name+token  将name+token封装成Map
        String name = userInfo.getName();
        if(StringUtils.isEmpty(name)){
            name=userInfo.getNickName();
            if(StringUtils.isEmpty(name)){
                name=userInfo.getPhone();
            }
        }

        Map map=new HashMap<>();
        map.put("name",name);
        map.put("token", JwtHelper.createToken(userInfo.getId(),name));
        map.put("userid",userInfo.getId());
        return map;
    }

    @Override
    public UserInfo selectUserByOpenid(String openid) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid",openid);

        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 微信扫码登录
     * @param loginVo
     * @return
     */
    @Transactional//开启事务,保证删除更新同时成功或者同时失败
    @Override
    public Map boundlePhone(LoginVo loginVo) {
        //1.对必要的参数进行非空校验
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        String openid = loginVo.getOpenid();
        if(StringUtils.isEmpty(openid)){
            throw new YyghException(20001,"openid不能为空");
        }
        if(StringUtils.isEmpty(code)){
            throw new YyghException(20001,"验证码不能为空");
        }
        if(StringUtils.isEmpty(phone)){
            throw new YyghException(20001,"手机号不能为空");
        }
        //2.对验证码进行校验
        String codeFromRedis = stringRedisTemplate.boundValueOps(phone).get();
        if(!code.equals(codeFromRedis)){
            throw new YyghException(20001,"验证码校验失败");
        }

        //3.根据openid查询到该微信用户(userInfo是否可为空?不可能)
        UserInfo userInfoByOpenId = this.selectUserByOpenid(openid);
        //4.根据手机号去查询一下
        UserInfo userInfoByPhone = this.getUserInfoByPhone(phone);
        //(1)手机号不存在,直接为微信用户绑定手机号
        if(userInfoByPhone==null){
            //手机号没有被注册过
            userInfoByOpenId.setPhone(phone);
            userInfoByOpenId.setUpdateTime(new Date());
            baseMapper.updateById(userInfoByOpenId);
            //返回的是name+token 用userInfoByOpenId对象里面的name+token
            return this.getMap(userInfoByOpenId);
        }else{
            if(StringUtils.isEmpty(userInfoByPhone.getOpenid())&&StringUtils.isEmpty(userInfoByPhone.getNickName())){
                //(2)手机号已经存在
                //①手机号存在但未绑定微信,也就是根据手机号查询到的userInfo中的openid和nickname为空
                userInfoByPhone.setOpenid(userInfoByOpenId.getOpenid());
                userInfoByPhone.setNickName(userInfoByOpenId.getNickName());
                //先删除后添加
                baseMapper.deleteById(userInfoByOpenId.getId());
                baseMapper.updateById(userInfoByPhone);
                return this.getMap(userInfoByPhone);
            }else {
                //(2)该手机号已被某微信绑定,直接抛出异常说明手机号被占用
                throw new YyghException(20001,"手机号已被占用,请更换手机号");
            }
        }
    }

    @Override
    public UserInfo getByUserId(Long userId) {
        UserInfo userInfo = baseMapper.selectById(userId);
        this.packUserInfo(userInfo);
        return userInfo;
    }

    @Override
    public void userAuth(Long userId, UserAuthVo userAuthVo) {
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.setName(userAuthVo.getName());
        userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
        userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
        userInfo.setCertificatesType(userAuthVo.getCertificatesType());
        userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());  //1-认证中 已提交用户信息
        userInfo.setUpdateTime(new Date());
        baseMapper.updateById(userInfo);
    }

    /**
     *按条件进行分页查询
     */
    @Override
    public Page<UserInfo> selectPage(Integer pageNum, Integer pageSize, UserInfoQueryVo queryVo) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();


        String keyword = queryVo.getKeyword();
        if(!StringUtils.isEmpty(keyword)){
            queryWrapper.like("name",keyword);
        }

        Integer status = queryVo.getStatus();
        if(!StringUtils.isEmpty(status)){
            queryWrapper.eq("status",status);
        }

        Integer authStatus = queryVo.getAuthStatus();
        if(!StringUtils.isEmpty(authStatus)){
            queryWrapper.eq("auth_status",authStatus);
        }

        String createTimeBegin = queryVo.getCreateTimeBegin();
        if(!StringUtils.isEmpty(createTimeBegin)){
            queryWrapper.ge("create_time",createTimeBegin);
        }

        String createTimeEnd = queryVo.getCreateTimeEnd();
        if(!StringUtils.isEmpty(createTimeEnd)){
            queryWrapper.lt("create_time",createTimeEnd);
        }

        Page<UserInfo> userInfoPage = new Page<>(pageNum, pageSize);

        baseMapper.selectPage(userInfoPage,queryWrapper);

        userInfoPage.getRecords().forEach(userInfo -> {
            this.packUserInfo(userInfo);
        });

        return userInfoPage;
    }

    /**
     * 用户的锁定和解锁
     * @param userId
     * @param status
     */
    @Override
    public void updateStatus(Long userId, Integer status) {
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.setStatus(status);
        userInfo.setUpdateTime(new Date());
        baseMapper.updateById(userInfo);
    }

    /**
     *  根据用户的id查询 就诊人列表+用户信息
     */
    @Override
    public Map getUserDetail(Long id) {
        Map map=new HashMap<>();

        UserInfo userInfo = baseMapper.selectById(id);
        this.packUserInfo(userInfo);

        List<Patient> patientList = patientService.findPatientList(id);

        map.put("userInfo",userInfo);
        map.put("patientList",patientList);
        return map;
    }

    //修改用户的认证状态
    @Override
    public void updateAuthStatus(Long userId, Integer authStatus) {
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.setAuthStatus(authStatus);
        userInfo.setUpdateTime(new Date());
        baseMapper.updateById(userInfo);
    }

    @Override
    public boolean checkUserAuthStatus(Long userId) {
        UserInfo userInfo = baseMapper.selectById(userId);

        String name = userInfo.getName();
        String certificatesType = userInfo.getCertificatesType();
        String certificatesNo = userInfo.getCertificatesNo();
        String certificatesUrl = userInfo.getCertificatesUrl();

        String host = "https://idcardcheck2.hzylgs.com";
        String path = "/api-mall/api/id_card_v2/check";
        String method = "POST";
        String appcode = "84bccdc0578641fd90d4a1a16f9768ff";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();


        bodys.put("name", name);
        bodys.put("idcard", certificatesNo);


        try {
                /**
                 * 重要提示如下:
                 * HttpUtils请从
                 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
                 * 下载
                 *
                 * 相应的依赖请参照
                 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
                 */
             HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);

             //System.out.println(response.toString());
                //获取response的body
                //System.out.println(EntityUtils.toString(response.getEntity()));

            String s = EntityUtils.toString(response.getEntity());
            Map map = JSON.parseObject(s, Map.class);
            Object data = map.get("data");
            String s1 = String.valueOf(data);
            Map map1 = JSON.parseObject(s1, Map.class);
            Object result = map1.get("result");
            String s2 = String.valueOf(result);
            int result1 = Integer.parseInt(s2);
            if(result1==0){
                return true;
            }
        } catch (Exception e) {
             e.printStackTrace();
         }
      return false;
  }

    //为param中的authStatusString赋值
    private void packUserInfo(UserInfo userInfo) {
        String statusNameByStatus = AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus());
        //从userInfo中获取输入的状态值,如果和枚举里面的有一样的,就返回是什么状态
        userInfo.getParam().put("authStatusString",statusNameByStatus);
        userInfo.getParam().put("statusString",userInfo.getStatus()==0?"锁定":"正常");
    }

    private UserInfo getUserInfoByPhone(String phone) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);
        return userInfo;
    }
    private Map getMap(UserInfo userInfo){

        if(userInfo.getStatus()==0){
            throw new YyghException(20001,"账号已被锁定,请联系管理员");
        }

        String name = userInfo.getName();
        if(StringUtils.isEmpty(name)){
            name=userInfo.getNickName();
            if(StringUtils.isEmpty(name)){
                name=userInfo.getPhone();
            }
        }

        Map map=new HashMap<>();
        map.put("name",name);
        map.put("token", JwtHelper.createToken(userInfo.getId(),name));
        return map;
    }
}
